/********************************************************************************
 * @file    hal_sntp.c
 * @brief   sntp 操作
 * 
 * @author  nzttj
 * @date    2025-03-24
 * @version 1.0
 * 
 * Copyright (C) 2025 nztt
 * 
 * 本软件使用 GNU 通用公共许可证 (GPL) 第 3 版授权。
 * 
 * 您可以自由使用、修改、分发本软件，但必须遵守以下条件：
 * 1. 源代码必须开放，且您修改后的代码也必须以 GPL 许可证发布。
 * 2. 发布或分发本软件时，必须附带本许可证，并提供源代码或获取源代码的方式。
 * 
 * 本软件按“原样”提供，不附带任何担保，使用风险由用户自行承担。
 * 
 ********************************************************************************/

#include "hal_sntp.h"

#include <string.h>
#include "esp_log.h"
#include "lwip/apps/sntp.h"

#define SNTP_SYNC_INTERVAL  (3600 * 1000)   // 同步间隔, 1小时

static const char *TAG = "hal_sntp";
static char *s_sntp_servers[SNTP_MAX_SERVERS];

// 组件内部状态
static struct
{
    bool initialized;       // 初始化标志
    bool time_synced;       // 时间同步状态
    sntp_sync_cb_t user_cb; // 用户回调函数
} s_sntp_ctx;

// 内部同步状态回调
static void sntp_sync_callback(struct timeval *tv)
{
    s_sntp_ctx.time_synced = true;
    ESP_LOGI(TAG, "Time sync successful, time: %s", ctime(&tv->tv_sec));

    if (s_sntp_ctx.user_cb)
    {
        s_sntp_ctx.user_cb(tv);
    }
}

hal_sntp_err_t hal_sntp_init(void)
{
    if (s_sntp_ctx.initialized)
    {
        // ESP_LOGW(TAG, "Already initialized");
        return HAL_SNTP_OK;
    }

    s_sntp_ctx.time_synced = false;
    sntp_stop();
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED);   // 立即同步模式
    sntp_set_sync_interval(SNTP_SYNC_INTERVAL); // 同步间隔
    sntp_set_time_sync_notification_cb(sntp_sync_callback);
    for (int i = 0; i < SNTP_MAX_SERVERS; i++)
    {
        if (s_sntp_servers[i])
        {
            sntp_setservername(i, s_sntp_servers[i]);
        }
    }
    sntp_init();

    s_sntp_ctx.initialized = true;
    ESP_LOGI(TAG, "SNTP initialized");
    return HAL_SNTP_OK;
}

void hal_sntp_deinit(void)
{
    if (!s_sntp_ctx.initialized)
        return;

    sntp_stop();
    sntp_set_time_sync_notification_cb(NULL);
    memset(&s_sntp_ctx, 0, sizeof(s_sntp_ctx));
    ESP_LOGI(TAG, "SNTP deinitialized");
}

hal_sntp_err_t hal_sntp_add_server(uint8_t index, const char *server)
{
    if (index >= SNTP_MAX_SERVERS)
    {
        ESP_LOGE(TAG, "Invalid server index %d", index);
        return HAL_SNTP_ERR_MAX_SERVERS;
    }

    if (s_sntp_servers[index])
    {
        free(s_sntp_servers[index]);
    }

    s_sntp_servers[index] = strdup(server);
    if (!s_sntp_servers[index])
    {
        ESP_LOGE(TAG, "Failed to duplicate server name");
        return HAL_SNTP_ERR_OTHER;
    }

    return HAL_SNTP_OK;
}

void hal_sntp_set_sync_callback(sntp_sync_cb_t cb)
{
    s_sntp_ctx.user_cb = cb;
}

bool hal_sntp_is_time_synced(void)
{
    return s_sntp_ctx.time_synced;
}